package simple.flow.config.shiro;

import simple.flow.modules.system.dto.user.LoginUser;
import simple.flow.modules.system.service.SysUserService;
import simple.flow.util.IpUtil;
import simple.flow.util.JwtUtil;
import simple.flow.util.WebUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;


/**
 * 用户认证信息
 *
 * @author lhd
 * @since 2025/4/2 17:24
 */

@Slf4j
@Component
public class UserRealm extends AuthorizingRealm {

    @Resource
    private SysUserService userService;

    /**
     * 重写 supports 方法，确保支持自定义的token
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 自定义授权方法
     *
     * @param principals 授权信息
     * @return 添加的授权信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("进入自定义授权方法");
        // 创建对象，存储当前登录的用户的权限和角色
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        // 1. 获取当前用户身份信息
        String username = principals.getPrimaryPrincipal().toString();

        // 2. 调用接口方法获取用户的角色信息
        List<String> roles = userService.getUserRoles(username);
        System.out.println("当前用户角色信息：" + roles);
        authorizationInfo.addRoles(roles);

        // 3. 调用接口方法获取用户角色的权限信息
        //List<String> permissions = userService.getUserPermissions(roles);
        //System.out.println("当前用户权限信息：" + permissions);
        // 存储权限信息
        //authorizationInfo.addStringPermissions(permissions);

        // 4. 返回登录的信息
        return authorizationInfo;
    }

    /**
     * 自定义登录认证方法
     *
     * @param token 认证信息 Token 包含了用户输入的用户名和密码等信息。
     * @return 当前登录用户信息
     * @throws AuthenticationException 认证异常
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 1. 获取用户token
        String jwtToken = (String) token.getCredentials();
        if (jwtToken == null) {
            HttpServletRequest req = WebUtil.getHttpServletRequest();
            log.error("身份认证失败，token为空，请求url：{}，请求IP：{}", req.getRequestURL(), IpUtil.getIpAddr(req));
            throw new AuthenticationException("token为空");
        }

        // 2, 校验token是否正确
        String username = JwtUtil.getUsername(jwtToken);
        if (StringUtils.isEmpty(username)) {
            throw new AuthenticationException("token非法");
        }

        // 3. 获取登录用户数据
        LoginUser user = userService.getLoginUser(username);

        // 4. 判断并将数据完成封装
        if (user != null) {
            return new SimpleAuthenticationInfo(user, jwtToken, getName());
        }

        throw new AuthenticationException("用户认证失败");
    }

}